{ "cells": [ { "cell_type": "markdown", "id": "a63a2902", "metadata": {}, "source": [ "# Extract Image using Semantic Segmentation" ] }, { "attachments": {}, "cell_type": "markdown", "id": "0be8ce12", "metadata": {}, "source": [ "---\n", "\n", "This notebook's CI test result for us-west-2 is as follows. CI test results in other regions can be found at the end of the notebook. \n", "\n", "![This us-west-2 badge failed to load. Check your device's internet connectivity, otherwise the service is currently unavailable](https://prod.us-west-2.tcx-beacon.docs.aws.dev/sagemaker-nb/us-west-2/introduction_to_amazon_algorithms|jumpstart_semantic_segmentation|Amazon_JumpStart_Semantic_Segmentation_Extract_Image.ipynb)\n", "\n", "---" ] }, { "cell_type": "markdown", "id": "f452ac0d", "metadata": {}, "source": [ "---\n", "Welcome to Amazon [SageMaker JumpStart](https://docs.aws.amazon.com/sagemaker/latest/dg/studio-jumpstart.html)! You can use JumpStart to solve many Machine Learning tasks through one-click in SageMaker Studio, or through [SageMaker JumpStart API](https://sagemaker.readthedocs.io/en/stable/doc_utils/jumpstart.html). In this demo notebook, we demonstrate how to use the JumpStart API for Semantic Segmentation. Semantic segmentation is the task of detecting and delineating each distinct object of interest appearing in an image. It is a fine-grained, pixel-level approach to developing computer vision applications. It tags every pixel in an image with a class label from a predefined set of classes. It differs from Instance Segmentation in the following: Semantic Segmentation treats multiple objects of the same class as a single entity whereas Instance Segmentation treats multiple objects of the same class as distinct individual instances.\n", "\n", "\n", "In this notebook, we demonstrate two use cases of semantic segmentation models: \n", "\n", "* How to use pre-trained Semantic Segmentation models for inference.\n", "* How to use JumpStart transfer learning algorithm to finetune a Semantic Segmentation model on a custom dataset.\n", "\n", "---" ] }, { "cell_type": "markdown", "id": "296d90b4", "metadata": {}, "source": [ "1. [Set Up](#1.-Set-Up)\n", "2. [Select a pre-trained model](#2.-Select-a-pre-trained-model)\n", "3. [Run inference on the pre-trained model](#3.-Run-inference-on-the-pre-trained-model)\n", " * [Retrieve JumpStart Artifacts & Deploy an Endpoint](#3.1.-Retrieve-JumpStart-Artifacts-&-Deploy-an-Endpoint)\n", " * [Download an example image for inference](#3.2.-Download-an-example-image-for-inference)\n", " * [Query endpoint and parse response](#3.3.-Query-endpoint-and-parse-response)\n", " * [Display model predictions](#3.4.-Display-model-predictions)\n", "4. [Display and Extract Model Predicted Image](#4.-Display-and-Extract-Model-Predicted-Image)\n", " * [Extract Model Predicted Image](#4.1.-Extract-Model-Predicted-Image)\n", " * [Display Extracted Model Predicted Image](#4.2.-Display-Extracted-Model-Predicted-Image)\n", " * [Clean up the endpoint](#4.3.-Clean-up-the-endpoint)\n", " " ] }, { "cell_type": "markdown", "id": "3563ed3b", "metadata": {}, "source": [ "Note: This notebook was tested on ml.t3.medium instance in Amazon SageMaker Studio with Python 3 (Data Science) kernel and in Amazon SageMaker Notebook instance with conda_python3 kernel." ] }, { "cell_type": "markdown", "id": "9bc89b5a", "metadata": {}, "source": [ "## 1. Set Up" ] }, { "cell_type": "markdown", "id": "3ad4b892", "metadata": {}, "source": [ "---\n", "Before executing the notebook, there are some initial steps required for set up. This notebook requires latest version of sagemaker and ipywidgets\n", "\n", "---" ] }, { "cell_type": "code", "execution_count": null, "id": "cf3875b8", "metadata": {}, "outputs": [], "source": [ "!pip install 'sagemaker<3.0' ipywidgets --upgrade --quiet" ] }, { "cell_type": "markdown", "id": "e60178f9", "metadata": {}, "source": [ "### Permissions and environment variables\n", "\n", "---\n", "To train and host on Amazon SageMaker, we need to set up and authenticate the use of AWS services. Here, we use the execution role associated with the current notebook as the AWS account role with SageMaker access. It has necessary permissions, including access to your data in S3. \n", "\n", "---" ] }, { "cell_type": "code", "execution_count": null, "id": "5aa0d7ad", "metadata": {}, "outputs": [], "source": [ "import sagemaker, boto3, json\n", "from sagemaker import get_execution_role\n", "\n", "aws_role = get_execution_role()\n", "aws_region = boto3.Session().region_name\n", "sess = sagemaker.Session()" ] }, { "cell_type": "markdown", "id": "c6e83358", "metadata": {}, "source": [ "### 2. Select a pre-trained model\n", "\n", "***\n", "Here, we download jumpstart model_manifest file from the jumpstart s3 bucket, filter out all the Semantic Segmentation models and select a model for inference.\n", "***" ] }, { "cell_type": "code", "execution_count": null, "id": "b8867dee", "metadata": {}, "outputs": [], "source": [ "from ipywidgets import Dropdown\n", "\n", "# download JumpStart model_manifest file.\n", "boto3.client(\"s3\").download_file(\n", " f\"jumpstart-cache-prod-{aws_region}\", \"models_manifest.json\", \"models_manifest.json\"\n", ")\n", "with open(\"models_manifest.json\", \"rb\") as json_file:\n", " model_list = json.load(json_file)\n", "\n", "# filter-out all the Semantic Segmentation models from the manifest list.\n", "semseg_models = []\n", "for model in model_list:\n", " model_id = model[\"model_id\"]\n", " if \"-semseg-\" in model_id and model_id not in semseg_models:\n", " semseg_models.append(model_id)\n", "\n", "print(f\"\\033[38;5;2mChose a model: \\033[0;0m\\n\")\n", "\n", "# display the model-ids in a dropdown to select a model for inference.\n", "model_dropdown = Dropdown(\n", " options=semseg_models,\n", " value=\"mxnet-semseg-fcn-resnet101-coco\",\n", " description=\"\",\n", " style={\"description_width\": \"initial\"},\n", " layout={\"width\": \"max-content\"},\n", ")\n", "display(model_dropdown)" ] }, { "cell_type": "code", "execution_count": null, "id": "d574d190", "metadata": {}, "outputs": [], "source": [ "# model_version=\"*\" fetches the latest version of the model\n", "model_id, model_version = model_dropdown.value, \"*\"" ] }, { "cell_type": "markdown", "id": "666256a5", "metadata": {}, "source": [ "## 3. Run inference on the pre-trained model\n", "\n", "***\n", "\n", "Using JumpStart, we can perform inference on the pre-trained model, even without fine-tuning it first on a new dataset. \n", "***" ] }, { "cell_type": "markdown", "id": "e2ab3628", "metadata": {}, "source": [ "### 3.1. Retrieve JumpStart Artifacts & Deploy an Endpoint\n", "\n", "***\n", "We retrieve the `deploy_image_uri`, `deploy_source_uri`, and `base_model_uri` for the pre-trained model. To host the pre-trained base-model, we create an instance of [`sagemaker.model.Model`](https://sagemaker.readthedocs.io/en/stable/api/inference/model.html) and deploy it.\n", "***" ] }, { "cell_type": "code", "execution_count": null, "id": "5c399f24", "metadata": {}, "outputs": [], "source": [ "from sagemaker import image_uris, model_uris, script_uris, hyperparameters\n", "from sagemaker.model import Model\n", "from sagemaker.predictor import Predictor\n", "from sagemaker.utils import name_from_base\n", "\n", "\n", "endpoint_name = name_from_base(f\"jumpstart-example-infer-{model_id}\")\n", "\n", "inference_instance_type = \"ml.m5.xlarge\"\n", "\n", "# Retrieve the inference docker container uri\n", "deploy_image_uri = image_uris.retrieve(\n", " region=None,\n", " framework=None, # automatically inferred from model_id\n", " image_scope=\"inference\",\n", " model_id=model_id,\n", " model_version=model_version,\n", " instance_type=inference_instance_type,\n", ")\n", "\n", "# Retrieve the inference script uri. This includes scripts for model loading, inference handling etc.\n", "deploy_source_uri = script_uris.retrieve(\n", " model_id=model_id, model_version=model_version, script_scope=\"inference\"\n", ")\n", "\n", "\n", "# Retrieve the base model uri\n", "base_model_uri = model_uris.retrieve(\n", " model_id=model_id, model_version=model_version, model_scope=\"inference\"\n", ")\n", "\n", "\n", "# Create the SageMaker model instance\n", "model = Model(\n", " image_uri=deploy_image_uri,\n", " source_dir=deploy_source_uri,\n", " model_data=base_model_uri,\n", " entry_point=\"inference.py\", # entry point file in source_dir and present in deploy_source_uri\n", " role=aws_role,\n", " predictor_cls=Predictor,\n", " name=endpoint_name,\n", ")\n", "\n", "# deploy the Model. Note that we need to pass Predictor class when we deploy model through Model class,\n", "# for being able to run inference through the sagemaker API.\n", "base_model_predictor = model.deploy(\n", " initial_instance_count=1,\n", " instance_type=inference_instance_type,\n", " predictor_cls=Predictor,\n", " endpoint_name=endpoint_name,\n", ")" ] }, { "cell_type": "markdown", "id": "ba3cc880", "metadata": {}, "source": [ "### 3.2. Download an example image for inference\n", "---\n", "We download an example image from the JumpStart assets S3 bucket.\n", "\n", "---" ] }, { "cell_type": "code", "execution_count": null, "id": "587d0ea4", "metadata": {}, "outputs": [], "source": [ "jumpstart_assets_s3_bucket = f\"jumpstart-cache-prod-{aws_region}\"\n", "pedestrian_img_key_prefix = \"inference-notebook-assets\"\n", "pedestrian_img = \"img_pedestrian.png\"\n", "\n", "boto3.client(\"s3\").download_file(\n", " jumpstart_assets_s3_bucket, f\"{pedestrian_img_key_prefix}/{pedestrian_img}\", pedestrian_img\n", ")" ] }, { "cell_type": "markdown", "id": "ffda396b", "metadata": {}, "source": [ "### 3.3. Query endpoint and parse response\n", "\n", "---\n", "Input to the endpoint is a single image in binary format. Response of the endpoint is a predicted label for each pixel in the image. \n", "\n", "---" ] }, { "cell_type": "code", "execution_count": null, "id": "e9522ba2", "metadata": {}, "outputs": [], "source": [ "import json\n", "\n", "\n", "def query(model_predictor, image_file_name):\n", " \"\"\"Query the model predictor.\"\"\"\n", "\n", " with open(image_file_name, \"rb\") as file:\n", " input_img_rb = file.read()\n", "\n", " query_response = model_predictor.predict(\n", " input_img_rb,\n", " {\n", " \"ContentType\": \"application/x-image\",\n", " \"Accept\": \"application/json;verbose\",\n", " },\n", " )\n", " return query_response\n", "\n", "\n", "def parse_response(query_response):\n", " \"\"\"Parse response and return predictions as well as the set of all labels and object labels present in the image.\"\"\"\n", " response_dict = json.loads(query_response)\n", " return response_dict[\"predictions\"], response_dict[\"labels\"], response_dict[\"image_labels\"]" ] }, { "cell_type": "code", "execution_count": null, "id": "abb1353a", "metadata": {}, "outputs": [], "source": [ "query_response = query(base_model_predictor, pedestrian_img)\n", "\n", "predictions, labels, image_labels = parse_response(query_response)\n", "print(\"Objects present in the picture:\", image_labels)" ] }, { "cell_type": "markdown", "id": "a7aab549", "metadata": {}, "source": [ "### 3.4. Display model predictions\n", "---\n", "Next, we display the bounding boxes overlaid on the original image. To get color palette for visualization, we borrow the VOC palette implementation from [GluonCV](https://cv.gluon.ai/_modules/gluoncv/utils/viz/segmentation.html#get_color_pallete) \n", "\n", "---" ] }, { "cell_type": "code", "execution_count": null, "id": "9d97c9f1", "metadata": {}, "outputs": [], "source": [ "import matplotlib.image as mpimg\n", "from matplotlib import pyplot as plt\n", "import numpy as np\n", "from PIL import Image\n", "\n", "\n", "def getvocpalette(num_cls):\n", " \"\"\"Get a color palette.\"\"\"\n", "\n", " n = num_cls\n", " palette = [0] * (n * 3)\n", " for j in range(0, n):\n", " lab = j\n", " palette[j * 3 + 0] = 0\n", " palette[j * 3 + 1] = 0\n", " palette[j * 3 + 2] = 0\n", " i = 0\n", " while lab > 0:\n", " palette[j * 3 + 0] |= ((lab >> 0) & 1) << (7 - i)\n", " palette[j * 3 + 1] |= ((lab >> 1) & 1) << (7 - i)\n", " palette[j * 3 + 2] |= ((lab >> 2) & 1) << (7 - i)\n", " i = i + 1\n", " lab >>= 3\n", " return palette\n", "\n", "\n", "def display_predictions(predictions):\n", " \"\"\"Display predictions with each pixel subsituted by the color of the corresponding label.\"\"\"\n", "\n", " palette = getvocpalette(256)\n", " npimg = np.array(predictions)\n", " npimg[npimg == -1] = 255\n", " mask = Image.fromarray(npimg.astype(\"uint8\"))\n", "\n", " mask.putpalette(palette)\n", " mask.save(\"Mask_putput.png\")\n", " mmask = mpimg.imread(\"Mask_putput.png\")\n", " plt.imshow(mask)" ] }, { "cell_type": "code", "execution_count": null, "id": "a75797ed", "metadata": {}, "outputs": [], "source": [ "display_predictions(predictions)" ] }, { "cell_type": "markdown", "id": "d2c811cc", "metadata": {}, "source": [ "### 4. Display and Extract Model Predicted Image\n", "\n", "---\n", "We now have the model predicted mask, so let's use it to extract the pedestrian image out of the original image.\n", "\n", "---" ] }, { "cell_type": "markdown", "id": "892aa8e2", "metadata": {}, "source": [ "### 4.1. Extract Model Predicted Image\n", "\n", "\n", "---\n", "Using the pixel data of model predicted mask, we overlay it on top of the image pixels to remove the background details and retrieve pedestrian image. After executing below cell, you can find the Final_pedestrian.jpg in your folder, which is the extracted image of the pedestrians. \n", "\n", "---\n" ] }, { "cell_type": "code", "execution_count": null, "id": "834eda90", "metadata": {}, "outputs": [], "source": [ "# Convert the pedestrian Image to JPEG so we get the pixel details\n", "im1 = Image.open(r\"img_pedestrian.png\")\n", "rgb_im1 = im1.convert(\"RGB\")\n", "rgb_im1.save(\"img_pedestrian-1.jpg\")\n", "\n", "# Convert the mask output to JPEG so we get the pixel details\n", "im2 = Image.open(r\"Mask_putput.png\")\n", "rgb_im2 = im2.convert(\"RGB\")\n", "rgb_im2.save(\"Mask_putput-1.jpg\")\n", "\n", "im1 = Image.open(\"img_pedestrian-1.jpg\")\n", "pixelMap1 = im1.load()\n", "im2 = Image.open(\"Mask_putput-1.jpg\")\n", "pixelMap2 = im2.load()\n", "width1, height1 = im1.size\n", "width2, height2 = im2.size\n", "\n", "\n", "# Set the height and width to the largest image\n", "\n", "if width2 > width1:\n", " width = width2\n", "else:\n", " width = width1\n", "\n", "if height2 > height1:\n", " height = height2\n", "else:\n", " height = height1\n", "\n", "\n", "for i in range(width): # for every col:\n", " for j in range(height): # For every row\n", " R1, G1, B1 = pixelMap2[i, j]\n", " if R1 != 0 and G1 != 0 and B1 != 0:\n", " pixelMap2[i, j] = pixelMap1[i, j]\n", " else:\n", " pixelMap2[i, j] = (0, 0, 0)\n", "\n", "\n", "im2 = im2.save(\"Final_Pedestrians.jpg\")" ] }, { "cell_type": "markdown", "id": "fcf590d2", "metadata": {}, "source": [ "\n", "---\n", "Let's display the original pedestrian image with the background included\n", "___" ] }, { "cell_type": "code", "execution_count": null, "id": "c93e92b4", "metadata": {}, "outputs": [], "source": [ "im1.show()" ] }, { "cell_type": "markdown", "id": "2c6b9450", "metadata": {}, "source": [ "### 4.2. Display Extracted Model Predicted Image\n", "---\n", "Display the pedestrian image after extraction \n", "___" ] }, { "cell_type": "code", "execution_count": null, "id": "6da8ba26", "metadata": {}, "outputs": [], "source": [ "im3 = Image.open(\"Final_Pedestrians.jpg\")\n", "im3.show()" ] }, { "cell_type": "markdown", "id": "b1b3025d", "metadata": {}, "source": [ "### 4.3. Clean up the endpoint" ] }, { "cell_type": "code", "execution_count": null, "id": "325f007e", "metadata": {}, "outputs": [], "source": [ "# Delete the SageMaker endpoint\n", "base_model_predictor.delete_model()\n", "base_model_predictor.delete_endpoint()" ] }, { "attachments": {}, "cell_type": "markdown", "id": "0361c639", "metadata": {}, "source": [ "## Notebook CI Test Results\n", "\n", "This notebook was tested in multiple regions. The test results are as follows, except for us-west-2 which is shown at the top of the notebook.\n", "\n", "![This us-east-1 badge failed to load. Check your device's internet connectivity, otherwise the service is currently unavailable](https://prod.us-west-2.tcx-beacon.docs.aws.dev/sagemaker-nb/us-east-1/introduction_to_amazon_algorithms|jumpstart_semantic_segmentation|Amazon_JumpStart_Semantic_Segmentation_Extract_Image.ipynb)\n", "\n", "![This us-east-2 badge failed to load. Check your device's internet connectivity, otherwise the service is currently unavailable](https://prod.us-west-2.tcx-beacon.docs.aws.dev/sagemaker-nb/us-east-2/introduction_to_amazon_algorithms|jumpstart_semantic_segmentation|Amazon_JumpStart_Semantic_Segmentation_Extract_Image.ipynb)\n", "\n", "![This us-west-1 badge failed to load. Check your device's internet connectivity, otherwise the service is currently unavailable](https://prod.us-west-2.tcx-beacon.docs.aws.dev/sagemaker-nb/us-west-1/introduction_to_amazon_algorithms|jumpstart_semantic_segmentation|Amazon_JumpStart_Semantic_Segmentation_Extract_Image.ipynb)\n", "\n", "![This ca-central-1 badge failed to load. Check your device's internet connectivity, otherwise the service is currently unavailable](https://prod.us-west-2.tcx-beacon.docs.aws.dev/sagemaker-nb/ca-central-1/introduction_to_amazon_algorithms|jumpstart_semantic_segmentation|Amazon_JumpStart_Semantic_Segmentation_Extract_Image.ipynb)\n", "\n", "![This sa-east-1 badge failed to load. Check your device's internet connectivity, otherwise the service is currently unavailable](https://prod.us-west-2.tcx-beacon.docs.aws.dev/sagemaker-nb/sa-east-1/introduction_to_amazon_algorithms|jumpstart_semantic_segmentation|Amazon_JumpStart_Semantic_Segmentation_Extract_Image.ipynb)\n", "\n", "![This eu-west-1 badge failed to load. Check your device's internet connectivity, otherwise the service is currently unavailable](https://prod.us-west-2.tcx-beacon.docs.aws.dev/sagemaker-nb/eu-west-1/introduction_to_amazon_algorithms|jumpstart_semantic_segmentation|Amazon_JumpStart_Semantic_Segmentation_Extract_Image.ipynb)\n", "\n", "![This eu-west-2 badge failed to load. Check your device's internet connectivity, otherwise the service is currently unavailable](https://prod.us-west-2.tcx-beacon.docs.aws.dev/sagemaker-nb/eu-west-2/introduction_to_amazon_algorithms|jumpstart_semantic_segmentation|Amazon_JumpStart_Semantic_Segmentation_Extract_Image.ipynb)\n", "\n", "![This eu-west-3 badge failed to load. Check your device's internet connectivity, otherwise the service is currently unavailable](https://prod.us-west-2.tcx-beacon.docs.aws.dev/sagemaker-nb/eu-west-3/introduction_to_amazon_algorithms|jumpstart_semantic_segmentation|Amazon_JumpStart_Semantic_Segmentation_Extract_Image.ipynb)\n", "\n", "![This eu-central-1 badge failed to load. Check your device's internet connectivity, otherwise the service is currently unavailable](https://prod.us-west-2.tcx-beacon.docs.aws.dev/sagemaker-nb/eu-central-1/introduction_to_amazon_algorithms|jumpstart_semantic_segmentation|Amazon_JumpStart_Semantic_Segmentation_Extract_Image.ipynb)\n", "\n", "![This eu-north-1 badge failed to load. Check your device's internet connectivity, otherwise the service is currently unavailable](https://prod.us-west-2.tcx-beacon.docs.aws.dev/sagemaker-nb/eu-north-1/introduction_to_amazon_algorithms|jumpstart_semantic_segmentation|Amazon_JumpStart_Semantic_Segmentation_Extract_Image.ipynb)\n", "\n", "![This ap-southeast-1 badge failed to load. Check your device's internet connectivity, otherwise the service is currently unavailable](https://prod.us-west-2.tcx-beacon.docs.aws.dev/sagemaker-nb/ap-southeast-1/introduction_to_amazon_algorithms|jumpstart_semantic_segmentation|Amazon_JumpStart_Semantic_Segmentation_Extract_Image.ipynb)\n", "\n", "![This ap-southeast-2 badge failed to load. Check your device's internet connectivity, otherwise the service is currently unavailable](https://prod.us-west-2.tcx-beacon.docs.aws.dev/sagemaker-nb/ap-southeast-2/introduction_to_amazon_algorithms|jumpstart_semantic_segmentation|Amazon_JumpStart_Semantic_Segmentation_Extract_Image.ipynb)\n", "\n", "![This ap-northeast-1 badge failed to load. Check your device's internet connectivity, otherwise the service is currently unavailable](https://prod.us-west-2.tcx-beacon.docs.aws.dev/sagemaker-nb/ap-northeast-1/introduction_to_amazon_algorithms|jumpstart_semantic_segmentation|Amazon_JumpStart_Semantic_Segmentation_Extract_Image.ipynb)\n", "\n", "![This ap-northeast-2 badge failed to load. Check your device's internet connectivity, otherwise the service is currently unavailable](https://prod.us-west-2.tcx-beacon.docs.aws.dev/sagemaker-nb/ap-northeast-2/introduction_to_amazon_algorithms|jumpstart_semantic_segmentation|Amazon_JumpStart_Semantic_Segmentation_Extract_Image.ipynb)\n", "\n", "![This ap-south-1 badge failed to load. Check your device's internet connectivity, otherwise the service is currently unavailable](https://prod.us-west-2.tcx-beacon.docs.aws.dev/sagemaker-nb/ap-south-1/introduction_to_amazon_algorithms|jumpstart_semantic_segmentation|Amazon_JumpStart_Semantic_Segmentation_Extract_Image.ipynb)\n" ] } ], "metadata": { "instance_type": "ml.t3.medium", "kernelspec": { "display_name": "Python 3 (Data Science 3.0)", "language": "python", "name": "python3__SAGEMAKER_INTERNAL__arn:aws:sagemaker:us-east-1:081325390199:image/sagemaker-data-science-310-v1" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.6" } }, "nbformat": 4, "nbformat_minor": 5 }